package com.navinfo.app.hd

import android.app.Activity
import android.app.ProgressDialog
import android.content.Intent
import android.os.*
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.*
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.lzf.easyfloat.EasyFloat
import com.navinfo.collect.library.data.NavinfoPbfFileUtils
import com.navinfo.collect.library.data.RealmUtils
import com.navinfo.collect.library.data.entity.GeometryFeatureEntity
import com.navinfo.collect.library.data.entity.LayerEntity
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.source.MapLifeDBTileSource
import com.navinfo.collect.library.map.source.RealmDBTileSource
import com.navinfo.collect.library.system.Constant
import com.navinfo.collect.library.theme.NavThemeUtils
import com.navinfo.collect.library.theme.ThemeEntity
import com.navinfo.collect.library.utils.GeometryTools
import io.realm.Realm
import me.rosuh.filepicker.bean.FileItemBeanImpl
import me.rosuh.filepicker.config.AbstractFileFilter
import me.rosuh.filepicker.config.FilePickerManager
import org.dom4j.Document
import org.dom4j.io.SAXReader
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.oscim.android.theme.AssetsRenderTheme
import org.oscim.core.MapPosition
import org.oscim.core.MercatorProjection
import org.oscim.event.Gesture
import org.oscim.event.GestureListener
import org.oscim.event.MotionEvent
import org.oscim.layers.Layer
import org.oscim.layers.tile.vector.VectorTileLayer
import org.oscim.layers.tile.vector.labeling.LabelLayer
import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook
import org.oscim.map.Map
import java.io.File
import java.io.InputStreamReader
import java.nio.charset.Charset
import kotlin.math.abs
import kotlin.streams.toList

// 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
class MainActivity : AppCompatActivity() {
    private val mapView: NIMapView by lazy { findViewById(R.id.mapview) }
    private val btnImportPbf:Button by lazy { findViewById(R.id.btn_import_pbf) }
    private val btnShowRefresh:Button by lazy { findViewById(R.id.btn_show_refresh) }
    private val btnShowPbfVector: Button by lazy { findViewById(R.id.btn_show_pbf_vector) }
    private val btnShowPbfTile: Button by lazy { findViewById(R.id.btn_show_pbf_tile) }
    private val btnShowWcdbTile: Button by lazy { findViewById(R.id.btn_show_wcdb_vector) }
    private val lvHdLayer: ListView by lazy { findViewById(R.id.hd_layer_list) }
    private val layerAdapter: HdLayerCheckboxAdapter by lazy { HdLayerCheckboxAdapter(MainActivity@this) }
    private val btnThemeEdit: Button by lazy { findViewById(R.id.btn_theme_edit) }

    private val spnTileArray: Spinner by lazy { findViewById(R.id.spn_tile_array) }
    private val btnTileFly: Button by lazy { findViewById(R.id.btn_tile_fiy) }
    private val edtTileX: EditText by lazy { findViewById(R.id.edt_tile_x) }
    private val edtTileY: EditText by lazy { findViewById(R.id.edt_tile_y) }
    private val hdVectorTileSource: RealmDBTileSource by lazy { RealmDBTileSource() }
    private val baseVectorLayer : VectorTileLayer by lazy { VectorTileLayer(mapView.vtmMap, hdVectorTileSource) }
    private val labelLayer: LabelLayer by lazy { LabelLayer(mapView.vtmMap, baseVectorLayer, LabelTileLoaderHook(), 15) }
    private lateinit var loadingDialog: ProgressDialog
    private lateinit var display: HdItemDetailDisplay

    val aFilter = object : AbstractFileFilter() {
        override fun doFilter(listData: ArrayList<FileItemBeanImpl>): ArrayList<FileItemBeanImpl> {
            return ArrayList(listData.filter { item ->
                // 文件夹或是图片，则被滤出来，然后新建一个 ArrayList 返回给调用者即可
                ((item.isDir) || (item.fileName.endsWith(".pbf")))
            })
        }}

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        loadingDialog = ProgressDialog(MainActivity@this)
        loadingDialog.setCancelable(false)
        MapManager.instance.init(mapView)
        mapView.setGridLayerVisiable(true)
        mapView.addDefaultVectorTileLayer(NIMapView.MAP_THEME.DEFAULT)
        mapView.vtmMap.viewport().maxZoomLevel = 25

        // 显示图层列表
        lvHdLayer.adapter = layerAdapter

        btnImportPbf.setOnClickListener {
            try {
                FilePickerManager
                    .from(this@MainActivity)
                    .filter(aFilter)
                    .forResult(FilePickerManager.REQUEST_CODE)
            } catch (e: Exception) {
                Log.e("MainActivity：", e.toString())
            }
        }

        btnShowPbfVector.setOnClickListener {
            if (!mapView.vtmMap.layers().contains(baseVectorLayer)) {
                mapView.vtmMap.layers().add(baseVectorLayer)
            }
            if (!mapView.vtmMap.layers().contains(labelLayer)) {
                mapView.vtmMap.layers().add(labelLayer)
            }
            /*val poi3DLayer: Poi3DLayer = Poi3DLayer(mapView.vtmMap, vectorTileLayer)
            // 增加对应的key和Model对应的关系
            poi3DLayer.addModel(VtmModels.STREETLAMP, Tag("name", "traffic_light_3d"))
            mapView.vtmMap.layers().add(poi3DLayer)*/
            mapView.switchTileVectorLayerTheme(null)
            // 获取当前位置对应的tile号

            mapView.vtmMap.updateMap(true)
            // 更新图层列表
            val layerEntityList = Realm.getInstance(RealmUtils.getInstance().realmConfiguration)
                .where(LayerEntity::class.java).findAll()
            layerAdapter.refreshData(layerEntityList)
            layerAdapter.notifyDataSetChanged()
        }

        btnShowPbfTile.setOnClickListener{
            mapView.vtmMap.setTheme(
                AssetsRenderTheme(
                    this@MainActivity.getAssets(),
                    "",
                    "navdefault.xml"
                ), true)
            val tileNum = spnTileArray.selectedItem.toString();
            var mapPosition = MapPosition()
            mapPosition.setZoomLevel(18)
            mapPosition.setPosition(40.22379988, 116.19389920499998)
            mapView.vtmMap.animator().animateTo(mapPosition)
        }

        btnShowRefresh.setOnClickListener {
            mapView.vtmMap.updateMap()
        }

        btnTileFly.setOnClickListener {
            if (edtTileX.text.toString().equals("")) {
                Toast.makeText(this@MainActivity, "请输入tile的X值", Toast.LENGTH_SHORT).show()
            }
            if (edtTileY.text.toString().equals("")) {
                Toast.makeText(this@MainActivity, "请输入tile的Y值", Toast.LENGTH_SHORT).show()
            }
            val longitude = MercatorProjection.tileXToLongitude(edtTileX.text.toString().toLong(), Constant.OVER_ZOOM.toByte())
            val latitude = MercatorProjection.tileYToLatitude(edtTileY.text.toString().toLong(), Constant.OVER_ZOOM.toByte())
            mapView.vtmMap.animator().animateTo(MapPosition(latitude, longitude, MercatorProjection.zoomLevelToScale(18)))
        }

        mapView.getVtmMap().events.bind(Map.UpdateListener { e, mapPosition -> run {
            mapView.setBaseRasterVisiable(mapPosition.zoomLevel < 15)
        } })
        btnShowWcdbTile.setOnClickListener{
/*            object: Thread() {
                override fun run() {
                    super.run()
                    //获取可以显示的数据图层
                    val layerManagerList =
                        MapLifeDataBase.getDatabase(this@MainActivity, Constant.ROOT_PATH + "/coremap.db").layerManagerDao.findList(1)
                    if(layerManagerList!=null){
                        Log.d("initMapLifeSource", "" + layerManagerList.size)
                    }
                }
            }.start()*/

            val mapLifeDBTileSource =
                MapLifeDBTileSource(this@MainActivity, Constant.ROOT_PATH + "/coremap.db")
            val vectorTileLayer = VectorTileLayer(mapView.vtmMap, mapLifeDBTileSource)
            mapView.switchTileVectorLayerTheme(null)
            val reslut: Boolean = mapView.vtmMap.layers().add(vectorTileLayer)
            Log.d("initMapLifeSource", "" + reslut)
            mapView.vtmMap.updateMap(true)
            val mapPosition = MapPosition()
            mapPosition.setZoomLevel(20)
            mapPosition.setPosition(40.0793985, 116.250138)
            mapView.vtmMap.animator().animateTo(mapPosition)
        }

        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }

//        baseVectorLayer.addHook(object:TileLoaderProcessHook {
//            override fun process(
//                tile: MapTile?,
//                layers: RenderBuckets?,
//                element: MapElement?
//            ): Boolean {
//                if (Constant.HAD_LAYER_INVISIABLE_ARRAY!=null&&Constant.HAD_LAYER_INVISIABLE_ARRAY.size>0) {
//                    for (layerType in Constant.HAD_LAYER_INVISIABLE_ARRAY) {
//                        if (element?.tags?.contains("layer", layerType) == true) {
//                            return true
//                        }
//                    }
//                }
//                return false
//            }
//
//            override fun complete(tile: MapTile?, success: Boolean) {
//            }
//
//        })

        btnThemeEdit.setOnClickListener {
            // 首先读取当前的默认theme
            val themeStream = assets.open("navtest.xml")
            val themeDoc = SAXReader().read(themeStream)
            val themeUtils = NavThemeUtils()

            val themeEntityList = mutableListOf<ThemeEntity>()
            val nav_styleTheme = ThemeEntity()
            nav_styleTheme.properties["k"] = "nav_style"
            val symbol_object_point = ThemeEntity()
            symbol_object_point.properties["k"]="symbol_object_point"
            symbol_object_point.properties["zoom-min"] = "10"
            symbol_object_point.properties["zoom-max"] = "22"
            nav_styleTheme.children.add(symbol_object_point)

            val start_level = ThemeEntity()
            start_level.properties["k"] = "start_level"
            symbol_object_point.children.add(start_level)
            themeEntityList.add(nav_styleTheme)

            val levelM = ThemeEntity()
            levelM.properties["v"] = "0"
            start_level.children.add(levelM)

            val symbol = ThemeEntity()
            symbol.name = "symbol"
            symbol.properties["src"] = "assets:symbols/square.svg"
            symbol.properties["symbol-width"] = "24"
            symbol.properties["symbol-height"] = "24"
            levelM.children.add(symbol)
//            themeUtils.loadThemeEntity(InputStreamReader(themeStream, Charset.forName("utf-8")).readText(), themeEntityList)
//            println(InputStreamReader(themeStream, Charset.forName("utf-8")).readText())
            println(themeUtils.loadThemeEntity(themeDoc.asXML(), themeEntityList))
        }

        mapView.vtmMap.layers().add(MapReceiver())
        display = HdItemDetailDisplay(mapView.vtmMap, this@MainActivity)
    }

    inner class MapReceiver: Layer(mapView.vtmMap), GestureListener {
        override fun onGesture(g: Gesture?, e: MotionEvent?): Boolean {
            // 如果当前hd数据没有加载，提示用户
            if (!mapView.vtmMap.layers().contains(baseVectorLayer)) {
                Toast.makeText(this@MainActivity, "Hd地图尚未加载！", Toast.LENGTH_SHORT).show()
                return false
            }
            // 获取用户点击事件
            if (g is Gesture.Tap) {
                val geoPoint = mapView.vtmMap.viewport().fromScreenPoint(e!!.x, e!!.y)
                // 根据geoPoint查询其在20级下的tile号
                val tileX = MercatorProjection.longitudeToTileX(geoPoint.longitude, Constant.OVER_ZOOM.toByte())
                val tileY = MercatorProjection.latitudeToTileY(geoPoint.latitude, Constant.OVER_ZOOM.toByte())
                // 根据geoPoint查询数据
                val realmQuery = Realm.getInstance(RealmUtils.getInstance().realmConfiguration)
                    .where(GeometryFeatureEntity::class.java)
                    .equalTo("tileX", tileX).and().equalTo("tileY", tileY)
                // 筛选不显示的数据
                if (Constant.HAD_LAYER_INVISIABLE_ARRAY != null && Constant.HAD_LAYER_INVISIABLE_ARRAY.size > 0) {
                    realmQuery.beginGroup()
                    for (type in Constant.HAD_LAYER_INVISIABLE_ARRAY) {
                        realmQuery.notEqualTo("name", type)
                    }
                    realmQuery.endGroup()
                }
                val allDataList = realmQuery.findAll()

                val pointGeometry = GeometryTools.createGeometry(geoPoint)
                // 获取该点位对应的10个像素范围的box
                var buffer = 20
                if (mMap.getMapPosition().zoomLevel>20) {
                    buffer = buffer.shl(mMap.mapPosition.zoomLevel-20)
                }
                val p1 = mMap.viewport().fromScreenPoint(e.x + buffer, e.y + buffer)
                val searchDistance: Double = abs(p1.latitude - geoPoint.latitude)
                val envelope = pointGeometry.buffer(searchDistance).envelope
                // 再从allDataList中筛选与点击位置相交的数据
                val filterList = allDataList.stream().filter { item ->
                    GeometryTools.createGeometry(item.geometry).intersects(envelope)
                }.toList()

                if (EasyFloat.isShow("HD-Layer")) {
                    EasyFloat.dismiss("HD-Layer")
                }
                if (filterList == null || filterList.isEmpty()) {
                    Toast.makeText(this@MainActivity,"此区域没有数据！", Toast.LENGTH_SHORT).show()
                    return false
                }
                val layout = LayoutInflater.from(this@MainActivity).inflate(R.layout.lv_select_hd_item, null)
                val lvHdItem = layout.findViewById<ListView>(R.id.lv_hd_item)
                val adapter = ArrayAdapter<String>(this@MainActivity, android.R.layout.activity_list_item, android.R.id.text1)
                val nameList = filterList.stream().map { it -> it.name }.toList()
                adapter.addAll(nameList)
                lvHdItem.adapter = adapter
                lvHdItem.setOnItemClickListener {
                        adapterView:AdapterView<*>, view: View, index:Int, var4: Long ->
                    val selectEntity = filterList[index]
                    // 高亮显示选中的元素
                    display.highLightHdItem(selectEntity)
                }
                EasyFloat.with(this@MainActivity).setLayout(layout)
                    .setTag("HD-Layer")
                    .setGravity(Gravity.RIGHT or Gravity.CENTER_VERTICAL, 0, 0)
                    .registerCallback {
                        dismiss {
                            display.clearHightLayer()
                        }
                    }.show()
//                    .forEach {
//                    println(it.name)
//                    Toast.makeText(this@MainActivity,it.name, Toast.LENGTH_SHORT).show() }
            }
            return false
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
    }

    @Subscribe
    fun onEventOnMainThread(msg: Message) {
        when (msg.what) {
            0x101-> { // 刷新图层
                val layerVisiable = msg.obj as kotlin.collections.Map<String, Boolean>
                Constant.setVisibleTypeMap(layerVisiable)
//                mapView.vtmMap.updateMap(true)
                mapView.vtmMap.clearMap()
            }
        }
    }

    @RequiresApi(Build.VERSION_CODES.N)
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when(requestCode) {
            FilePickerManager.REQUEST_CODE-> {
                if (resultCode == Activity.RESULT_OK) {
                    val files = FilePickerManager.obtainData()
                    Log.d("MainActivity：", "用户选中的文件是$files")
//                    Realm.getInstance(RealmUtils.getInstance().realmConfiguration).where(GeometryFeatureEntity::class.java).findFirst()
                    if (files.isNullOrEmpty()) {
                        Toast.makeText(this@MainActivity, "没有选中任何文件", Toast.LENGTH_SHORT).show()
                    } else {
                        loadingDialog.show()
                        // 开启线程插入数据
                        object: Thread() {
                            override fun run() {
                                super.run()
                                Log.d("Realm-file:", files.size.toString())
                                // 用户选中了对应的pbf数据
                                val pbfFileUtils = NavinfoPbfFileUtils()
                                val startTime = System.currentTimeMillis()
                                Realm.getInstance(RealmUtils.getInstance().realmConfiguration).beginTransaction()
                                for (file in files) {
                                    val geometryEntityList = pbfFileUtils.parserGisFile(File(file))
                                    Realm.getInstance(RealmUtils.getInstance().realmConfiguration).insertOrUpdate(geometryEntityList)
                                }
                                Realm.getInstance(RealmUtils.getInstance().realmConfiguration).commitTransaction()
                                val endTime = System.currentTimeMillis()
                                System.out.println("All-Time:"+(endTime-startTime))

                                Realm.compactRealm(RealmUtils.getInstance().realmConfiguration)


                                System.out.println("Arrow-All-Time: 数据处理结束")
                                handler.sendEmptyMessage(0x101)
                                // 获取当前共有多少种元素
                                val layerResults =
                                    Realm.getInstance(RealmUtils.getInstance().realmConfiguration)
                                        .where(LayerEntity::class.java).findAll()
                                layerResults.stream().forEach{ println(it.layerName)}
                            }
                        }.start()

                    }
                } else {
                    Toast.makeText(this@MainActivity, "没有选择任何东西~", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
    private val handler = object:Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when(msg.what) {
                0x101 -> loadingDialog.hide()
            }
        }
    }
}